package snippets.cse524.activeDates.evaluation;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

public final class BatchEvaluator {
	public static final void main(String[] args) throws FileNotFoundException {

		Scanner in = new Scanner(new File(args[0]));

		final Map<String, List<Double>> perMethodErrors = new HashMap<String, List<Double>>();
		final Map<String, Map<String, Double>> perSampleError = new HashMap<String, Map<String, Double>>();
		final Map<String, Lifespan> lifeSpans = new HashMap<String, Lifespan>();

		final Set<String> methods = new HashSet<String>();
		Pattern year = Pattern.compile("^([0-9]{4})");

		while (in.hasNextLine()) {
			String[] parts = StringUtils.split(in.nextLine().trim(), '\t');

			if (parts.length == 0)
				continue;

			String name = parts[0];
			Lifespan real = new Lifespan(Integer.parseInt(parts[1]),
					Integer.parseInt(parts[2]));

			int loc = 3;

			perSampleError.put(name, new HashMap<String, Double>());
			lifeSpans.put(name, real);

			while (loc < parts.length) {
				String method = "";
				while (!year.matcher(parts[loc]).find()) {
					method += parts[loc++];
				}

				int beginYear = Integer.parseInt(parts[loc++]);
				int endYear = Integer.parseInt(parts[loc++]);

				Lifespan estimate = new Lifespan(beginYear, endYear);
				Double squaredError = LifespanEvaluator.squaredError(real,
						estimate);

				methods.add(method);
				perSampleError.get(name).put(method, squaredError);
			}
		}

		for (String method : methods) {
			perMethodErrors.put(method, new ArrayList<Double>());
		}

		for (String name : perSampleError.keySet()) {
			for (String method : methods) {
				if (perSampleError.get(name).containsKey(method)) {
					perMethodErrors.get(method).add(
							perSampleError.get(name).get(method));
				} else {
					perMethodErrors.get(method).add(
							LifespanEvaluator.missingSquaredError(lifeSpans
									.get(name)));
				}
			}
		}

		List<String> sortedMethods = new ArrayList<String>(methods);

		Collections.sort(sortedMethods, new Comparator<String>() {
			@Override
			public int compare(String left, String right) {
				return sum(perMethodErrors.get(left)) > sum(perMethodErrors
						.get(right)) ? 1 : -1;
			}
		});

		for (String method : sortedMethods) {
			System.out
					.println(method + "\t" + sum(perMethodErrors.get(method)) / perSampleError.keySet().size());
		}
	}

	public static double sum(Collection<? extends Number> nums) {
		double s = 0.0;

		for (Number num : nums) {
			s += num.doubleValue();
		}

		return s;
	}
}
